package com.ruoyi.service.impl;


import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.entity.UserWechat;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.mapper.UserWechatMapper;
import com.ruoyi.common.service.UserWechatService;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户微信绑定信息 Service 实现类
 * @author 0617
 */
@Service
@RequiredArgsConstructor
public class UserWechatServiceImpl extends ServiceImpl<UserWechatMapper, UserWechat> implements UserWechatService {

    private final UserWechatMapper userWechatMapper;

    @Override
    public UserWechat getByOpenid(String openid) {
        if (openid == null || openid.trim().isEmpty()) {
            return null;
        }
        LambdaQueryWrapper<UserWechat> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserWechat::getOpenid, openid);
        return this.getOne(wrapper);
    }

    @Override
    public UserWechat getByUnionid(String unionid) {
        if (unionid == null || unionid.trim().isEmpty()) {
            return null;
        }
        LambdaQueryWrapper<UserWechat> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserWechat::getUnionid, unionid);
        return this.getOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindWeChatUser(UserWechat userWechat) {
        if (userWechat == null || userWechat.getOpenid() == null) {
            throw new IllegalArgumentException("微信用户信息不完整");
        }

        LambdaQueryWrapper<UserWechat> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserWechat::getOpenid, userWechat.getOpenid());

        UserWechat existing = this.getOne(wrapper);

        if (existing != null) {
            // 更新已有记录（保留主键）
            userWechat.setId(existing.getId());
            return this.updateById(userWechat);
        } else {
            // 新增绑定
            return this.save(userWechat);
        }
    }

    /**
     * 示例：使用自动填充时，可重写父类方法
     */
//    @Override
//    public boolean save(UserWechat entity) {
//        // 可在此做额外处理，如日志、加密等
//        return super.save(entity);
//    }


    /*@Value("${wechat.miniprogram.appid}")*/
    private final String appid ="wxd7f24f3c2475d5d7";

    /*@Value("${wechat.miniprogram.secret}")*/
    private final String secret = "97305e3983e1fd460f4cd0002d5a7c3d";


    @Autowired
    private ISysUserService sysUserService; // 系统用户服务（假设存在）

    @Autowired
    private TokenService tokenService; // 复用平台的token服务

    @Resource
    private UserDetailsService userDetailsService;


    private static final int USERNAME_LENGTH = 8; // 随机用户名长度

    @Transactional
    public String login(String code) {
        try {
            // 1. 调用微信接口获取openid和session_key
            String url = "https://api.weixin.qq.com/sns/jscode2session";
            Map<String, Object> params = new HashMap<>(4);
            params.put("appid", appid);
            params.put("secret", secret);
            params.put("js_code", code);
            params.put("grant_type", "authorization_code");

            String result = HttpUtil.get(url, params);
            JSONObject jsonObject = JSONUtil.parseObj(result);

            // 处理微信接口错误
            if (jsonObject.containsKey("errcode") && jsonObject.getInt("errcode") != 0) {
                String errMsg = jsonObject.getStr("errmsg", "未知错误");
                AsyncManager.me().execute(AsyncFactory.recordLogininfor("微信用户", Constants.LOGIN_FAIL, "微信接口错误：" + errMsg));
                throw new ServiceException("微信登录失败：" + errMsg);
            }

            // 2. 提取微信返回的标识信息
            String openid = jsonObject.getStr("openid");
            String unionid = jsonObject.getStr("unionid");
            if (StringUtils.isBlank(openid)) {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor("微信用户", Constants.LOGIN_FAIL, "未获取到openid"));
                throw new ServiceException("微信登录失败：未获取到用户标识");
            }

            // 3. 查询是否已绑定系统用户（通过openid关联）
            UserWechat userWechat = baseMapper.selectOne(new QueryWrapper<UserWechat>()
                    .eq("openid", openid));
            SysUser sysUser = null;

            // 4. 未绑定则创建新用户并关联
            if (userWechat == null) {
                // 生成唯一随机用户名（确保不重复）
                String username = generateUniqueUsername();
                // 创建系统用户（密码加密，默认状态正常）
                sysUser = new SysUser();
                sysUser.setUserName(username);
                sysUser.setNickName("微信用户_" + username.substring(0, 4));
                sysUser.setPassword(SecurityUtils.encryptPassword(username));
                sysUser.setDelFlag("0");
                sysUser.setStatus("0");
                sysUser.setIsVip(0);
                sysUser.setCreateTime(new Date());
                sysUserService.registerUser(sysUser); // 保存系统用户


                // 创建微信用户关联记录
                userWechat = new UserWechat();
                userWechat.setOpenid(openid);
                userWechat.setUnionid(unionid);
                userWechat.setUserId(sysUser.getUserId()); // 关联系统用户ID
                userWechat.setCreatedAt(LocalDateTime.now());
                userWechat.setUpdatedAt(LocalDateTime.now());
                baseMapper.insert(userWechat);
            } else {
                // 5. 已绑定则更新信息并查询系统用户
                sysUser = sysUserService.selectUserById(userWechat.getUserId());
                if (sysUser == null) {
                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(openid, Constants.LOGIN_FAIL, "关联的系统用户不存在"));
                    throw new ServiceException("用户信息异常，请重新绑定");
                }
                // 更新微信用户信息（如unionid变更）
                boolean needUpdate = false;
                if (StringUtils.hasText(unionid) && !unionid.equals(userWechat.getUnionid())) {
                    userWechat.setUnionid(unionid);
                    needUpdate = true;
                }
                if (needUpdate) {
                    userWechat.setUpdatedAt(LocalDateTime.now());
                    baseMapper.updateById(userWechat);
                }
            }

            // 6. 构建登录用户对象（适配现有token生成逻辑）
           /* UserDetails userDetails = userDetailsService.loadUserByUsername(sysUser.getUserName());
            if (!(userDetails instanceof LoginUser)) {
                throw new ServiceException("用户信息格式错误");
            }
            LoginUser loginUser = (LoginUser) userDetails;*/
            LoginUser loginUser = new LoginUser();
            loginUser.setUserId(sysUser.getUserId());
            loginUser.setUser(sysUser);
            // 补充其他必要字段（如权限、角色等，参考平台登录的LoginUser构建）

            // 7. 记录登录信息（复用平台的登录日志逻辑）
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.LOGIN_SUCCESS, "微信登录成功"));
            recordLoginInfo(sysUser.getUserId());
            // 8. 生成token（复用现有tokenService）
            return tokenService.createToken(loginUser);

        } catch (ServiceException e) {
            // 已知业务异常直接抛出
            throw e;
        } catch (Exception e) {
            log.error("微信登录异常", e);
            AsyncManager.me().execute(AsyncFactory.recordLogininfor("微信用户", Constants.LOGIN_FAIL, "系统异常"));
            throw new ServiceException("登录异常，请稍后重试");
        }
    }




    /**
     * 生成唯一的随机用户名（确保不重复）
     */
    private String generateUniqueUsername() {
        String prefix = "wx_";
        while (true) {
            // 生成8位随机数字（首位非0）
            String randomNum = RandomUtil.randomNumbers(USERNAME_LENGTH);
            if (randomNum.startsWith("0")) {
                continue;
            }
            String username = prefix + randomNum;
            // 检查用户名是否已存在
            if (sysUserService.count(username) == 0) {
                return username;
            }
        }
    }

    /**
     * 记录登录信息（复用平台登录的相同逻辑）
     */
    private void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(new Date());
        sysUserService.updateUser(sysUser);
    }


   /* *//**
     * 绑定手机号
     *//*
    @Override
    public UserWechat bindPhone(String encryptedData, String iv, String token) {
        try {
            // 1. 验证token
            if (!tokenService.verifyToken(token)) {
                throw new RuntimeException("token无效或已过期");
            }

            // 2. 从token中获取openid
            String openid = JwtUtils.getOpenidFromToken(token);
            if (!StringUtils.hasText(openid)) {
                throw new RuntimeException("获取用户信息失败");

            }

            // 3. 查询用户
            UserWechat userWechat = baseMapper.selectOne(new QueryWrapper<UserWechat>()
                    .eq("openid", openid));
            if (userWechat == null) {
                throw new RuntimeException("用户不存在");
            }

            // 4. 获取sessionKey（实际项目中应从安全存储中获取）
            String sessionKey = getSessionKeyFromStorage(openid); // 需实现此方法

            // 5. 解密手机号（需实现微信加密数据解密逻辑）
            String phoneNumber = decryptPhoneNumber(encryptedData, iv, sessionKey); // 需实现此方法

            // 6. 更新用户信息（假设UserWechat有phone相关字段，这里只是示例）
            // userWechat.setPhone(phoneNumber);
            userWechat.setUpdatedAt(LocalDateTime.now());
            baseMapper.updateById(userWechat);

            return userWechat;
        } catch (Exception e) {
            log.error("绑定手机号异常", e);
            throw new RuntimeException("绑定手机号异常，请稍后重试");
        }
        }

    *//**
     * 获取当前登录用户信息
     *//*
    @Override
    public UserWechat getUserInfo(String token) {
        try {
            // 1. 验证token
            if (!JwtUtils.verifyToken(token)) {
                new RuntimeException("token无效或已过期");

            }

            // 2. 从token中获取openid
            String openid = JwtUtils.getOpenidFromToken(token);
            if (!StringUtils.hasText(openid)) {
                throw new RuntimeException("获取用户信息失败");
            }

            // 3. 查询用户信息
            UserWechat userWechat = baseMapper.selectOne(new QueryWrapper<UserWechat>()
                    .eq("openid", openid));
            if (userWechat == null) {
                throw new RuntimeException("用户不存在");
            }


            return userWechat;
        } catch (Exception e) {
        throw new RuntimeException("获取用户信息异常，请稍后重试");
        }
    }

    *//**
     * 微信公众号登录
     *//**//*
    @Override
    public UserWechat mpLogin(String code, String redirectUri) {
        try {
            // 1. 调用微信公众号接口获取access_token和openid
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
            Map<String, String> params = new HashMap<>();
            params.put("appid", mpAppid);
            params.put("secret", mpSecret);
            params.put("code", code);
            params.put("grant_type", "authorization_code");

            String result = HttpUtils.sendGet(url, params);
            JSONObject jsonObject = JSONObject.parseObject(result);

            // 检查是否有错误
            if (jsonObject.containsKey("errcode")) {
                int errCode = jsonObject.getIntValue("errcode");
                if (errCode != 0) {
                    return AjaxResult.error("微信公众号登录失败：" + jsonObject.getString("errmsg"));
                }
            }

            // 2. 获取相关信息
            String openid = jsonObject.getString("openid");
            String unionid = jsonObject.getString("unionid");
            String accessToken = jsonObject.getString("access_token");
            String refreshToken = jsonObject.getString("refresh_token");
            int expiresIn = jsonObject.getIntValue("expires_in");

            if (!StringUtils.hasText(openid)) {
                return AjaxResult.error("获取openid失败");
            }

            // 3. 查询或创建用户
            UserWechat userWechat = baseMapper.selectOne(new QueryWrapper<UserWechat>()
                    .eq("openid", openid));

            if (userWechat == null) {
                userWechat = new UserWechat();
                userWechat.setOpenid(openid);
                userWechat.setUnionid(unionid);
                userWechat.setCreatedAt(LocalDateTime.now());
                userWechat.setUpdatedAt(LocalDateTime.now());
                baseMapper.insert(userWechat);
            } else {
                userWechat.setUpdatedAt(LocalDateTime.now());
                userWechat.setAccessToken(accessToken);
                userWechat.setRefreshToken(refreshToken);
                userWechat.setExpiresIn(expiresIn);
                if (StringUtils.hasText(unionid) && !unionid.equals(userWechat.getUnionid())) {
                    userWechat.setUnionid(unionid);
                }
                baseMapper.updateById(userWechat);
            }

            // 4. 生成token
            String token = JwtUtils.generateToken(openid);

            return AjaxResult.success(userWechat).put("token", token);
        } catch (Exception e) {
            log.error("微信公众号登录异常", e);
            return AjaxResult.error("登录异常，请稍后重试");
        }
    }
*//*
    *//**
     * 从存储中获取sessionKey（实际项目中需实现）
     *//*
    private String getSessionKeyFromStorage(String openid) {
        // 实际项目中应从安全存储（如Redis）中获取sessionKey
        return "";
    }

    *//**
     * 解密手机号（实际项目中需实现）
     *//*
    private String decryptPhoneNumber(String encryptedData, String iv, String sessionKey) {
        // 实现微信加密数据解密逻辑，参考微信官方文档
        return "";
    }*/
}